/*
    Yelo: Open Sauce SDK

    Copyright (C) 2005-2010  Kornner Studios (http://kornner.com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <TagGroups/Halo1/TagGroupDefinitions.hpp>

namespace Yelo
{
	namespace Enums
	{
		enum {
			k_maximum_number_of_attachments_per_object = 8,
		};
	};

	namespace TagGroups
	{
		struct object_attachment_definition
		{
			tag_reference type;
			tag_string marker;
			struct {
				_enum primary_scale;
				_enum secondary_scale;
				_enum change_color;
				PAD16;
			}function_inputs; // _object_definition.function_exports
			TAG_PAD(int32, 4);
		};

		struct object_definition_widget
		{
			tag_reference reference;
			TAG_PAD(int32, 4);
		};

		struct _object_definition
		{
			TAG_ENUM(runtime_object_type, Enums::object_type);
			struct _object_definition_flags {
				TAG_FLAG16(does_not_cast_shadow);
				TAG_FLAG16(transparent_self_occlusion);
				TAG_FLAG16(brighter_than_it_should);
				TAG_FLAG16(not_pathfinding_obstacle);
			}flags; BOOST_STATIC_ASSERT( sizeof(_object_definition_flags) == sizeof(word_flags) );

			real bounding_radius;
			real_point3d bounding_offset, origin_offset;
			real acceleration_scale;
			TAG_PAD(int32, 1);

			struct {
				TAG_FIELD(tag_reference, render_model,		"mod2");
				TAG_FIELD(tag_reference, animations,		"antr");
				TAG_PAD(int32, 10);
				TAG_FIELD(tag_reference, collision,			"coll");
				TAG_FIELD(tag_reference, physics,			"phys");
				TAG_FIELD(tag_reference, modifier_shader,	"shdr");
				TAG_FIELD(tag_reference, creation_effect,	"effe");
			}references;
			TAG_PAD(int32, 21);

			real render_bounding_radius;
			
			_enum function_exports[4];
			TAG_PAD(int32, 11);
			int16 hud_text_message_index;
			int16 forced_shader_permutation;

			TAG_TBLOCK(attachments, object_attachment_definition);

			TAG_TBLOCK(widgets, object_definition_widget);

			TAG_PAD(tag_block, 1); // object_function_definition
			TAG_PAD(tag_block, 1); // object_change_color_definition
			TAG_TBLOCK_(predicted_resources, predicted_resource); // predicted resources
		}; BOOST_STATIC_ASSERT( sizeof(_object_definition) == 0x17C );


		//////////////////////////////////////////////////////////////////////////

		struct projectile_material_response_block
		{
			struct _Flags {
				TAG_FLAG16(cannot_be_overpenetrated);
			}flags;

			struct _DefaultResult {
				TAG_ENUM(response, material_response);
				TAG_FIELD(tag_reference, effect, "effe");
				TAG_PAD(tag_reference, 1); // 16
			}default_result;

			struct _PotentialResult {
				TAG_ENUM(response, material_response);
				struct _Flags {
					TAG_FLAG16(only_against_units);
				}flags;
				TAG_FIELD(real, skip_fraction);
				TAG_FIELD(real_bounds, between, "degrees");
				TAG_FIELD(real_bounds, and, "world units per second");
				TAG_FIELD(tag_reference, effect, "effe");
				TAG_PAD(tag_reference, 1); // 16
			}potential_result;

			TAG_ENUM(scale_effects_by, effect_scale);
			TAG_PAD(_enum, 1); // 2
			TAG_FIELD(real, angular_noise, "degrees", "the angle of incidence is randomly perturbed by at most this amount to simulate irregularity.");
			TAG_FIELD(real, velocity_noise, "world units per second", "the velocity is randomly perturbed by at most this amount to simulate irregularity.");
			TAG_FIELD(tag_reference, detonation_effect, "effe");
			TAG_PAD(long, 6); // 24

			TAG_FIELD(real, initial_friction, "", "the fraction of the projectile's velocity lost on penetration");
			TAG_FIELD(real, max_distance, "", "the maximum distance the projectile can travel through on object of this material");

			TAG_FIELD(real, parallel_friction, "", "the fraction of the projectile's velocity parallel to the surface lost on impact");
			TAG_FIELD(real, perpendicular_friction, "", "the fraction of the projectile's velocity perpendicular to the surface lost on impact");
		}; BOOST_STATIC_ASSERT( sizeof(projectile_material_response_block) == 0xA0 );

		struct _projectile_definition
		{
			struct _projectile_definition_flags {
				TAG_FLAG(oriented_along_velocity);
				TAG_FLAG(ai_must_use_basllistic_aiming);
				TAG_FLAG(detonation_max_time_if_attached);
				TAG_FLAG(has_super_combining_explosion);
				//combine initial velocity with parent velocity
				//random attached detonation time
				//minimum unattached detonation time
			}flags; BOOST_STATIC_ASSERT( sizeof(_projectile_definition_flags) == sizeof(long_flags) );

			TAG_ENUM(detonation_timer_starts, projectile_detonation_timer_mode);
			TAG_ENUM(impact_noise, ai_sound_volume);

			TAG_ENUM(a_in, projectile_function);
			TAG_ENUM(b_in, projectile_function);
			TAG_ENUM(c_in, projectile_function);
			TAG_ENUM(d_in, projectile_function);

			TAG_FIELD(tag_reference, super_detonation, "effe");

			TAG_FIELD(real, ai_perception_radius, "world units");
			TAG_FIELD(real, collision_radius, "world units");

			TAG_FIELD(real, arming_time, "seconds", "won't detonate before this time elapses");
			TAG_FIELD(real, danger_radius, "world units", "");
			TAG_FIELD(tag_reference, effect, "effe", "");
			TAG_FIELD(real_bounds, timer, "seconds", "detonation countdown (zero is untimed)");
			TAG_FIELD(real, min_velocity, "world units per second", "detonates when slowed below this velocity");
			TAG_FIELD(real, max_range, "world units per second", "detonates after travelling this distance");

			TAG_FIELD(real, air_gravity_scale, "", "the proportion of normal gravity applied to the projectile when in air.");
			TAG_FIELD(real_bounds, air_damage_range, "world units", "the range over which damage is scaled when the projectile is in air.");
			TAG_FIELD(real, water_gravity_scale, "", "the proportion of normal gravity applied to the projectile when in water.");
			TAG_FIELD(real_bounds, water_damage_range, "world units", "the range over which damage is scaled when the projectile is in water.");
			TAG_FIELD(real, initial_velocity, "world units per second", "bullet's velocity when inflicting maximum damage");
			TAG_FIELD(real, final_velocity, "world units per second", "bullet's velocity when inflicting minimum damage");
			TAG_FIELD(real, guided_angular_velocity, "degrees per second", "");
			TAG_ENUM(detonation_noise, ai_sound_volume);
			TAG_PAD(_enum, 1); // 2

			TAG_FIELD(tag_reference, detonation_started,		"effe");
			TAG_FIELD(tag_reference, flyby_sound,				"snd!");
			TAG_FIELD(tag_reference, attached_detonation_damage,"jpt!");
			TAG_FIELD(tag_reference, impact_damage,				"jpt!");
			TAG_PAD(long, 3); // 12

			TAG_TBLOCK(material_responses, projectile_material_response_block);

		}; BOOST_STATIC_ASSERT( sizeof(_projectile_definition) == 0xD0 );

		//////////////////////////////////////////////////////////////////////////


		struct s_object_definition
		{
			enum { k_group_tag = 'obje' };

			_object_definition object;
		};

		struct s_projectile_definition : s_object_definition
		{
			enum { k_group_tag = 'proj' };

			_projectile_definition projectile;
		};
	};
};